/*
 * Main.java
 *
 * Created on 16/12/2007, 12:10:13 PM
 *
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ia;

import java.util.*;

/**
 *
 * @author Manuel Avalos
 * @author Arturo Ferreira
 * 
 */
/**
 * 
 * Clase principal para llevar a cabo la ejecucion del SPEA. Interaciona con 
 * las demas clases, imprimiendo el resultado obtenido.
 * 
 */
public class Main_SPEA {

    static Vector MejorFrente = new Vector();

    /**
     * 
     * Unico metodo del mail que contiene metodos de las demas clases para
     * llevar el algoritmo del SPEA.
     * @param args No utilizado.
     * 
     */
    public static void main(String[] args) {
        //Se crea un objeto de tipo Archivo.
        Archivo archivo = new Archivo();
        int generacion = 0;
        //Se crea un vector de tipo Matriz que almacenara la matriz de distancia y las matrices de flujos.

        try {
            //Leemos el archivo de entrada y obtenemos las matrices de datos.
            archivo.leer("C:\\Documents and Settings\\Ramon\\Escritorio\\instanciasPortFolioSelection\\us_dj_ind_avg-2001-2006.sd");


        } catch (Exception e) {
            e.printStackTrace();
        }
        for (int i = 0; i < 3; i++) {
            //Creamos un objeto de tipo Poblacion
            Poblacion poblacion = new Poblacion();
            //Generamos aleatoriamente la primera poblacion con los datos lesidos.
            poblacion.GenerarPoblacion(archivo.getPoblacion(), archivo.getActivos());
            //De manera a correr un cierto tiempo el algoritmo tenemos la variable "tiempo".
            //El valor que se suma a"tiempo" debe ser en milisegundos (180000 == 3min)
            long inicio = System.currentTimeMillis();
            while (generacion <= 1000) {
                System.out.println("Corrida "+ i +": "+(generacion / 1000.0) * 100 + "%");
                generacion++;
                //Se calcula el valor del vector de objetivos de los individuos con las matrices leidas.
                poblacion.calcularValorObjetivo(archivo.getCovarianza(), archivo.getRendimiento());
                //Identificamos los individuos no dominados y los copiamos a la Poblacion de No Dominados.
                Vector indicesNoDominados = poblacion.copiarNoDominados();
                //Borramos de la Poblacion Actual los individuos no dominados.
                poblacion.borrarNoDominados(indicesNoDominados);
                //Eliminamos los individuos dominados en la Poblacion de No Dominados.
                poblacion.eliminacionEnPnd();
                //Preguntamos si se excedio el limite de individuos en PnD, si se excedio se realiza el clustering.
                if (poblacion.sePasoElLimite()) {
                    poblacion.clusteringPnD();
                }
                //Asignamos el fitness a todos los individuos, tanto de la Poblacion Actual como la Poblacion de No Dominados.
                poblacion.AsignarFitness_SPEA();
                //Unimos ambas poblaciones,la Poblacion Actual y la Poblacion de No Dominados.
                Vector poblaciones = poblacion.unirPoblaciones();
                //Generamos la nueva poblacion que reemplazara a la Poblacion Actual.
                poblacion.seleccionYevolucionSPEA(poblaciones);
            }//Fin del ciclo del SPEA.
            long fin = System.currentTimeMillis();
            guardarMejoresSoluciones(poblacion.PnD);
            System.out.println("generacion= " + generacion);
            System.out.println("*******************Resultados de la corrida "+(i+1)+"******************************");
            System.out.println("Tiempo transcurrido = "+(fin-inicio)/60000.0);
            //Imprimimos el resultado obtenido, imprimiendo los individuos prsentes en la Poblacion de No Dominados.
            poblacion.resultado();
            generacion = 0;
        }//Fin de corrida.
        Individuo individuo;
        System.out.println("********************************************************************");
        System.out.println("*              Frente Pareto luego de las corridas                 *");
        System.out.println("********************************************************************");
        Main_SPEA.ImprimirFrente(MejorFrente);
//        for (int i = 0; i < Main_SPEA.MejorFrente.size(); i++) {
//            //Quitamos un individuo de la poblacion.
//            individuo = (Individuo) Main_SPEA.MejorFrente.elementAt(i);
//            //Imprimimos su cromosoma y valores de su vector de objetivos.
//            System.out.println("Individuo " + (i + 1) + " = "  + " " + individuo.toStringVecObjetivo());
//        }
        MetricasExtension m3 = new MetricasExtension();
        MetricaDistribucion m2 = new MetricaDistribucion(MejorFrente);
        double resultadoM3 = m3.CalcularMetricaExtension(MejorFrente);
        System.out.println("*************************La metrica de Extension es = "+resultadoM3+"*****************************");
        double resultadoM2 = m2.calcularMetrica();
        System.out.println("*************************La metrica de Distribucion es = "+resultadoM2+"*****************************");
    }

    public static void guardarMejoresSoluciones(Vector newFrente) {
        if (Main_SPEA.MejorFrente.size() == 0) {
            Main_SPEA.MejorFrente.addAll(newFrente);
        } else {
            //Agrego las nuevas soluciones y luego saco las no dominadas entre las mejores.
            Main_SPEA.MejorFrente.addAll(newFrente);
            Main_SPEA.MejorFrente = Poblacion.BuscarNoDominados(Main_SPEA.MejorFrente);
        }
    }
    public static void ImprimirFrente(Vector Frente)
    {
        //Para no imprimir los repetidos
        boolean repetido;
        Vector frenteNoRepetido=new Vector();
        for (int i = 0; i < Frente.size(); i++) {
            repetido=false;
            Individuo individuo_i = (Individuo) Frente.elementAt(i);
            for (int j = 0; j < frenteNoRepetido.size(); j++) {
                Individuo individuo_j = (Individuo) frenteNoRepetido.elementAt(j);
                if (individuo_i.igual(individuo_j)) {
                    repetido = true;
                    break;
                }
            }
            if (!repetido) {
                frenteNoRepetido.addElement(individuo_i);
            }
        }
        for (int i = 0; i < frenteNoRepetido.size(); i++) {
            Individuo individuo_i = (Individuo) frenteNoRepetido.elementAt(i);
            System.out.println("[" + i + "]" +  "     " + individuo_i.toStringVecObjetivo() + " ");
        }
    }
}